/+
Library dbapi - Simple database api for the D programming language.

Copyright (C) 2007 Myron Alexander (myron.alexander...gmail.com)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+/

module dbapi.internal.sqlite3.error;

import std.string : str = toString, replace;

import dbapi.base;

import sqlite.sqlite3;


private char[] getApiErrorMessage (sqlite3 *dbcon) {
   char* errmsg = sqlite3_errmsg (dbcon);
   return str (errmsg);
}

private struct DbError {
   char[] msg;
   int    code;
}

/**
 * Retrieve the error message and error code of the supplied sqlite connection.
 */
private DbError getApiError (sqlite3 *dbcon) {
   char* errmsg = sqlite3_errmsg (dbcon);
   int errcd    = sqlite3_errcode (dbcon);

   DbError e;
   e.msg = str (errmsg).dup;
   e.code = errcd;

   return e;
}

private char[] formatExceptionMessage (char[] msg, DbError err) {

   char[] newmsg;
   newmsg = replace (msg   , "$(errmsg)", err.msg);
   newmsg = replace (newmsg, "$(errcde)", str (err.code));

   return newmsg;
}

/**
 * Template to construct a dbapi exception containing sqlite error details.
 */
T SqliteError (T)(sqlite3 *dbcon, char[] msg) {

   static assert (is (T : SqlException),
      "Invalid type for SqliteError ("~typeid(typeof(T))~
      "). Must be SqlException or derivitive.");

   DbError err = getApiError (dbcon);

   char[] formatted = formatExceptionMessage (msg, err);

   T e = new T (formatted);

   static if (is (T : SqlDatabaseException)) {
      e.setVendorMsg (err.msg).setVendorCode (err.code);

   } else {
      e.setProperty (SqlDatabaseException.K_VENDORMSG, err.msg);
      e.setProperty (SqlDatabaseException.K_VENDORCODE, err.code);
   }

   return e;
}
